package com.redis.springtest.config;

import com.redis.springtest.RedisMessageListener;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

import java.time.Duration;
import java.util.HashSet;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 * Description:
 *
 * @author lzy
 * @create 2020 -04-21 下午4:52
 */
@Configuration
public class RedisConfig {

    /**
     * 定义一个string序列化器
     *
     * @return string redis serializer
     */
    @Bean
    StringRedisSerializer stringRedisSerializer() {
        return new StringRedisSerializer();
    }

    /**
     * Redis standalone configuration redis standalone configuration.
     *
     * @return the redis standalone configuration
     */
    @Bean
    RedisStandaloneConfiguration redisStandaloneConfiguration() {
        return new RedisStandaloneConfiguration("10.2.37.41", 6379);
    }

    /**
     * 定义一个连接工厂，默认会开启连接池模式
     * 基于Jedis
     *
     * @return redis connection factory
     */
    @Bean
    public RedisConnectionFactory jedisConnectionFactory() {
        return new JedisConnectionFactory(redisStandaloneConfiguration());
    }

    /**
     * 定义一个连接工厂，默认会开启连接池模式
     * 基于Lettuce
     *
     * @return redis connection factory
     */
    @Bean
    public RedisConnectionFactory lettuceConnectionFactory() {
        return new LettuceConnectionFactory(redisStandaloneConfiguration());
    }

    /**
     * 自定义一个redisTemplate
     *
     * @return redis template
     */
    @Bean
    public RedisTemplate redisTemplate() {
        RedisTemplate redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(lettuceConnectionFactory());
        redisTemplate.setKeySerializer(stringRedisSerializer());
        redisTemplate.setValueSerializer(stringRedisSerializer());
        redisTemplate.setHashKeySerializer(stringRedisSerializer());
        redisTemplate.setHashValueSerializer(stringRedisSerializer());
        return redisTemplate;
    }

    @Bean
    public RedisMessageListener redisMessageListener() {
        RedisMessageListener listener = new RedisMessageListener();
        listener.setRedisTemplate(redisTemplate());
        return listener;
    }

    @Bean
    RedisMessageListenerContainer redisMessageListenerContainer() {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        // 配置连接工厂
        container.setConnectionFactory(lettuceConnectionFactory());
        // 连接池, 这里只要线程池生存，才能继续监听
        container.setTaskExecutor(scheduler());
        // 增加消息监听
        container.addMessageListener(redisMessageListener(), new ChannelTopic("chat"));
        return container;
    }

    @Bean
    ThreadPoolTaskScheduler scheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(3);
        return scheduler;
    }

    @Bean
    public CacheManager redisCacheManager() {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofMinutes(10L))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer()))
                .disableCachingNullValues();

        Set<String> cacheNames = new HashSet<>();
        cacheNames.add("redisCacheManager");
        return RedisCacheManager.builder(lettuceConnectionFactory())
                .cacheDefaults(config)
                .initialCacheNames(cacheNames)
                .transactionAware()
                .build();

    }
}
